package cn.bluethink.timescaledb.service.impl;

import cn.bluethink.timescaledb.entity.Dynamic;
import cn.bluethink.timescaledb.entity.RequestDTO;
import cn.bluethink.timescaledb.mapper.DBHelpMapper;
import cn.bluethink.timescaledb.mapper.DynamicMapper;
import cn.bluethink.timescaledb.mapper.DynamicRowMapper;
import cn.bluethink.timescaledb.service.DynamicService;
import cn.bluethink.timescaledb.util.DBUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.*;

@Service
public class DynamicServiceImpl implements DynamicService {

    @Autowired
    DynamicMapper dynamicMapper;

    @Autowired
    DBHelpMapper dbHelpMapper;

    @Autowired
    JdbcTemplate jdbcTemplate;

    private Logger logger = LoggerFactory.getLogger(DynamicServiceImpl.class);

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public String insertBatch(RequestDTO requestDTO) {

        String result = "success";

        Integer res = dbHelpMapper.tableIsExit(requestDTO.getTableName());
        if (res != 0) {
            List<List<Object>> params = getParam(requestDTO);
            List<String> columns = dbHelpMapper.getColumnNamesByTableName(requestDTO.getTableName());
            Boolean whetherInsert = DBUtil.whetherInsert(columns, requestDTO.getTableKeys(),true);
            if (whetherInsert) {
                dynamicMapper.insertBatch(requestDTO, requestDTO.getTableKeys(), params);
                logger.info("插入已存在表:" + requestDTO.getTableName());
            } else {
                result = "表已存在,但由于表结构和上传文件结构不同无法保存,建议更换表名重试.";
            }
        } else {
            requestDTO.getTableKeys().subList(0, 2);
            dbHelpMapper.createTable(requestDTO.getTableName(), requestDTO.getTableKeys());
            dbHelpMapper.createHyperTable(requestDTO.getTableName(),"time");
            List<List<Object>> params = getParam(requestDTO);
            Map<String,Object> paramMap = new HashMap<>();
            paramMap.put("tableName",requestDTO.getTableName());
            paramMap.put("keys",requestDTO.getTableKeys());
            paramMap.put("params",params);
            dbHelpMapper.insertBatch(paramMap);
            logger.info("创建表:" + requestDTO.getTableName());
        }

        return result;
    }

    /**
     * 根据表名查询所有数据
     * @param tableName
     * @return
     */
    @Transactional(rollbackFor = {RuntimeException.class, SQLException.class})
    @Override
    public List<Dynamic> queryByTableName(String tableName) {
        Long  startTime = new Date().getTime();
        if (dbHelpMapper.tableIsExit(tableName) != 0){
            List<String> keys = dbHelpMapper.getColumnNamesByTableName(tableName);
            List<Dynamic> dynamics = jdbcTemplate.query("select * from " + tableName, new DynamicRowMapper(keys));
            Long endTime = new Date().getTime();
            logger.info("查询数据:" + dynamics + "---------------->查询整表共消耗:" + (endTime - startTime) + "ms");
            System.out.println("---------------->查询整表共消耗:" + (endTime - startTime) + "ms");
            return dynamics;
        }
        return null;
    }

    /**获取动态数据属性值(里面的每一个list<Object>就是一个dynamic数据)
     * @param requestDTO
     * @return
     */
    private List<List<Object>> getParam(RequestDTO requestDTO) {
        List<List<Object>> params = new ArrayList<>();
        for (Dynamic dynamic : requestDTO.getData()) {
            List<Object> param = new ArrayList<>();
            param.add(dynamic.getTime());
            param.add(dynamic.getNumber());
            for (Map<String, String> map : dynamic.getLocation()) {
                Iterator it = map.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry entry = (Map.Entry) it.next();
                    Object value = entry.getValue();
                    param.add(value);
                }
            }
            params.add(param);
        }
        return params;
    }
}
